
import { defineComponent, h, resolveComponent, ref, markRaw } from 'vue';
export let DynamicComponentEditor = defineComponent({
    emits: ['selected', 'unselected'],
    props: {
        editable: { type: Boolean }, maskColor: { type: String },
        group: {
            type: Object
        },
        compMethods: { type: Function },
        context: { type: Function }
    },
    data() {
        return {
            componentMap: markRaw({ map: new Map() }),
            selectedComponent: null,
            selectedElement: null,
            startX: 0, startY: 0,
            moving: false,
        }
    },
    methods: {
        r_edit_rect(dycmp) {
            if (dycmp) {
                let rect = dycmp.getBoundingClientRect();
                let rectR = this.$refs.comp.getBoundingClientRect();
                return h('div', {
                    class: 'selectedDynamicComponent',
                    ref: 'selectRect',
                    style: {
                        'position': 'absolute',
                        'border': '1px solid black',
                        'left': rect.x - rectR.x + 'px',
                        'top': rect.y - rectR.y + 'px',
                        'width': rect.width + 'px',
                        'height': rect.height + 'px',
                        // 'position': 'fixed',
                        'z-index': 199999999999
                    },
                    draggable: true,
                    'onClick.stop.prevent': this.onRectClick,
                    onDrag: this.onRectDrag,
                    onMousedown: this.onRectMousedown,
                    // onMousemove: this.onRectMousemove,
                    'onMouseup.stop.prevent': this.onRectMouseup,
                });
            }
        },
        onRectMouseup(event) {
            console.log(event);
            this.moving = false;
            let selectRect = this.$refs.selectRect;
            selectRect.style.cursor = "auto";
            let rect = selectRect.getBoundingClientRect();
            let selectedComponent = this.selectedComponent;
            selectedComponent.style.left = rect.left;
            selectedComponent.style.top = rect.top;
        },
        onMouseup(event) {
            // console.log(event);
            if (!this.moving) {
                return;
            }
            this.moving = false;
            let selectRect = this.$refs.selectRect;
            if (selectRect) {
                selectRect.style.cursor = "auto";
                selectRect = selectRect.getBoundingClientRect();

                let rangeRect = this.$refs.comp.getBoundingClientRect();

                let selectedComponent = this.selectedComponent;
                let id = selectedComponent.id;
                let data = this.componentMap.map.get(id);
                if (data && data.props && data.props.style) {
                    if (selectRect.left < rangeRect.left) {
                        this.selectedComponent = null;
                        this.selectedElement = null;
                        return;
                    }
                    if (selectRect.right > rangeRect.right) {
                        this.selectedComponent = null;
                        this.selectedElement = null;
                        return;
                    }
                    if (selectRect.top < rangeRect.top) {
                        this.selectedComponent = null;
                        this.selectedElement = null;
                        return;
                    }
                    if (selectRect.bottom > rangeRect.bottom) {
                        this.selectedComponent = null;
                        this.selectedElement = null;
                        return;
                    }
                    data.props.style.left = selectRect.left - rangeRect.left + 'px';
                    data.props.style.top = selectRect.top - rangeRect.top + 'px';
                }
            }
        },
        onMousemove(event) {
            if (!this.moving) {
                return;
            }
            var x = event.clientX - this.startX;
            var y = event.clientY - this.startY;

            let selectRect = this.$refs.selectRect;
            selectRect.style.left = x + "px";
            selectRect.style.top = y + "px";
        },
        onRectMousedown(e) {
            console.log(e);
            this.moving = true;
            let selectRect = this.$refs.selectRect;
            selectRect.style.cursor = "grabbing";
            selectRect.style.userSelect = "none";
            this.startX = e.clientX - selectRect.offsetLeft;
            this.startY = e.clientY - selectRect.offsetTop;
        },
        onRectDrag(e) {
            // console.log(e);
            var dt = e.dataTransfer;
            dt.setData("application/simpleDomEditorComponent", "");
        },
        dragOverEditor(e) {
            console.log(e);
        },
        getDyCmp(children, x, y) {
            for (let i = 0; i < children.length; i++) {
                let child = children[i];
                if (child.dataset.editable) {
                    if (child.dataset.editable == 'container') {
                        let subChild = this.getDyCmp(child.children, x, y);
                        if (subChild) {
                            return subChild;
                        }

                        let rect = child.getBoundingClientRect();
                        if (rect.left < x && rect.left + rect.width > x) {
                            if (rect.top < y && rect.top + rect.height > y) {
                                return child;
                            }
                        }
                    } else if (child.dataset.editable == 'true') {
                        let rect = child.getBoundingClientRect();
                        if (rect.left < x && rect.left + rect.width > x) {
                            if (rect.top < y && rect.top + rect.height > y) {
                                return child;
                            }
                        }
                    }
                }
            }
        },
        onRectClick(e) {
            console.log(e.x, e.y)
            e.preventDefault();
        },
        onClick(e) {
            let comp = this.$refs.comp;
            let children = comp.children;
            let dycmp = this.getDyCmp(children, e.x, e.y);
            this.selectedComponent = dycmp;
            if (dycmp) {
                let elem = document.getElementById(dycmp.id);
                this.selectedElement = elem;
            } else {
                this.selectedElement = null;
            }
        },
        r_slot(slot, editable) {
            if (Array.isArray(slot)) {
                return this.r_group(slot);
            } else if (typeof (slot) == 'object') {
                if (slot.props && slot.props.id) {
                    this.componentMap.map.set(slot.props.id, slot);
                }
                return this.r_groupChild(slot, editable);
            } else {
                return slot;
            }
        },
        r_groupChild(item, editable, group) {
            if (typeof (item) == 'string') {
                return item;
            }
            if (item.props && item.props.id) {
                this.componentMap.map.set(item.props.id, item);
            }
            let comp = resolveComponent(item.type);
            let slot = this.r_slot(item.props.slot, editable);
            if (editable) {
                let that = this;
                let p = {
                    x: parseInt(item.props.style.left),
                    y: parseInt(item.props.style.top),
                    w: parseInt(item.props.style.width),
                    h: parseInt(item.props.style.height),
                    r: parseInt(item.props.style.degree),
                    rotatable: true,
                    resizable: true,
                    draggable: true,
                    isConflictCheck: true,
                    snapTolerance: 20,
                    snap: true,
                    grid: [10, 10],
                    snapBorder: true,
                    parent: true,
                    onDragging(x, y) {
                        item.props.style.left = x + 'px';
                        item.props.style.top = y + 'px';
                    },
                    onDragstop(x, y) {
                        item.props.style.left = x + 'px';
                        item.props.style.top = y + 'px';
                    },
                    onResizing(x, y, w, h) {
                        item.props.style.width = w + 'px';
                        item.props.style.height = h + 'px';
                        item.props.style.left = x + 'px';
                        item.props.style.top = y + 'px';
                    },
                    onResizestop() {
                    },
                    onRotating: function (degree) {
                        item.props.style.transform = `rotate(${degree}deg)`;
                        item.props.style.degree = degree;
                    },
                    onRotatestop: function (degree) {
                        item.props.style.transform = `rotate(${degree}deg)`;
                        item.props.style.degree = degree;
                    },
                    onRotate: function (degree) {
                        item.props.style.transform = `rotate(${degree}deg)`;
                        item.props.style.degree = degree;
                    },
                    onActivated() {
                        that.$emit('selected', item);
                    },
                    onDeactivated() {
                        that.$emit('unselected');
                    }
                };
                let deleteIcon;
                if (group) {
                    if (typeof (item.deletable) == 'undefined' || item.deletable === true) {
                        // <Icon type="ios-close-circle" />
                        deleteIcon = (
                            h('div', {
                                style: { position: 'absolute', width: '15px', height: '15px', color: 'red', top: 0, right: 0, zIndex: 9999999 },
                            }, [
                                h(resolveComponent('Poptip'), {
                                    confirm: true,
                                    title: this.$t('删除'),
                                    transfer: true,
                                    'onOnOk'() {
                                        let idx = group.indexOf(item);
                                        if (idx >= 0) {
                                            group.splice(idx, 1);
                                        }
                                    }
                                }, [
                                    h(resolveComponent('Icon'), { type: "ios-close-circle" })])
                            ])
                        );
                    }
                }
                let itemProps = Object.assign({}, item.props);
                // Object.assign(itemProps.style, {  top: 0, left: 0 });
                itemProps.style = { width: '100%', height: '100%' };
                return h(
                    resolveComponent('VueDragResizeRotate')
                    , p
                    , [deleteIcon, h(comp, itemProps, slot)]
                );
            } else {
                let compMethods = this.compMethods(item);
                let p = Object.assign({}, item.props, compMethods);

                Object.keys(p).forEach(key => {
                    const value = p[key];
                    if (typeof value === 'function') {
                        p[key] = value.bind(p);
                    }
                });
                if (compMethods) {
                    let inject = {};
                    if (compMethods.inject) {
                        compMethods.inject.forEach(name => {
                            inject[name] = this.context(name);
                        });
                    }
                    p.inject = inject;
                }
                return h(comp, p, slot);
            }
        },
        r_group(group, editable) {
            if (Array.isArray(group)) {
                let g = group.map(child => {
                    return this.r_groupChild(child, editable, group);
                });
                return g;
            }
            if (group.props && group.props.id) {
                this.componentMap.map.set(group.props.id, group);
            }
        }
    },
    render() {
        if (this.editable) {
            let r = h('div', { ref: 'comp', 'data-editable': 'container', style: { width: '100%', height: '100%' } }, this.r_group(this.group, true));
            return r;
        } else {
            let r = h('div', { ref: 'comp', 'data-editable': 'container', style: { width: '100%', height: '100%' } }, this.r_group(this.group, false));
            return r;
        }
    }
});